package main;

import java.util.concurrent.Semaphore;
import java.util.HashMap;
import java.util.Iterator;

public class Repository {

	private HashMap<String,Semaphore> equipments;

	public Repository()
	{
		this.equipments=new HashMap<String,Semaphore>(30);
	}
	
	/**
	 * 
	 * @param name - type of equipment
	 * @return the amount of the equipment of type <name> exist in the repository
	 */
	public synchronized int getAmountOfEquipment(String name)
	{
		return equipments.get(name).availablePermits();
	}
	
	/**
	 * add all the equipment in the list given to the repository, by their order in the list
	 * @param equipmentListToAdd - hashmap in which the key is the name of the equipment and the units is the amount to add
	 */
	public void addEquipment(HashMap<String,Integer> equipmentListToAdd)
	{
		Iterator<String> i=equipmentListToAdd.keySet().iterator();
		while(i.hasNext())
		{
			String name=i.next();
			Integer amount=equipmentListToAdd.get(name);
			addEquipment(name, amount);
		}
	}
	
	/**
	 *	add <amount> units of an equipment of type <name> to the repository 
	 * @param name - name of equipment
	 * @param amount - the number of units to add
	 */
	public synchronized void addEquipment(String name,int amount)
	{
		if(!equipments.containsKey(name))
		{
			equipments.put(name, new Semaphore(0,true));
		}
		//System.out.println("repository check equipment "+name+" - "+equipments.get(name).availablePermits()+" units before addition");
		equipments.get(name).release(amount);
		//System.out.println("repository added equipment "+name+" - "+amount+" units.");
	}
	
	/**
	 * check the availability of a list of items in the repository. 
	 * in case some item has less than wanted amount in repository, it will enter a checkList with the amount missing
	 * this list will be returned to the user.
	 * in case all available, return null.
	 * @param list - a list of items to check
	 * @return NULL if everything available
	 * 			HashMap<String,Integer> contain the names and amount of missing equipment
	 */
	public synchronized HashMap<String,Integer> checkAvailability(HashMap<String,Integer> list)
	{
		HashMap<String,Integer> checkList=new HashMap<String,Integer>();
		Iterator<String> i=list.keySet().iterator();
		while(i.hasNext())		//compare list with repository equipments
		{
			String name=i.next();
			Integer amountMissing=new Integer(0); 
			amountMissing=list.get(name).intValue();
			if(equipments.containsKey(name))	//if equipment does exist in repository, then check if there is enough
			{
				amountMissing=amountMissing-equipments.get(name).availablePermits();
			}
			if(amountMissing>0)		//there is not enough of this equipment available for taking, if any
			{
				checkList.put(name, amountMissing);	//add to check list of thing to buy
			}				
		}
		
		if(checkList.isEmpty())
			return null;
		else
			return checkList;
	}
	
	/**
	 * try to take all items in the list given from the store. the first item to not have enough amount in store from will be returned
	 * @param neededEquipmentList - a list of items to take from the store
	 * @return a semaphore of the First item which doesnt have enough of it right at stock and cannot be taken already.
	 * 		 return NULL if not such item exist - if all items are taken! 
	 */
	public Semaphore takeEquipment(HashMap<String,Integer> neededEquipmentList)
	{
		Semaphore item=null;
		Iterator<String> i=neededEquipmentList.keySet().iterator();
		boolean itemsAvailable=true;
		while(i.hasNext() && itemsAvailable)
		{
			String name=i.next();
			Integer neededAmount=neededEquipmentList.get(name);
			item=takeEquipment(name);
			itemsAvailable=item.tryAcquire(neededAmount);
		}
		if(itemsAvailable)
		{
			return null;	//all items available and taken from storage
		}
		else
			return item;		//return the item found not available in storage
	}
	
	/**
	 * return a certain equipment from repository - without changing its content! 
	 * @param name - type of equipment
	 * @return a single semaphore in which the available permits represent the amount of this type of equipment
	 * 			 exist in the repository stock
	 */
	public Semaphore takeEquipment(String name)
	{
		
		return equipments.get(name);
	}
	
	/*
	
	public boolean takeEquipment(HashMap<String,Integer> equipments)
	{
		return true;
	}
	
	private boolean takeEquipment(String name, int amount,int daysToWait)
	{
		boolean isAcquired=true;
		if(daysToWait>0)	//as long as you got time for finishing the assignment, there is no need to get nervous 
		{
		try{
			isAcquired=equipments.get(name).tryAcquire(amount,daysToWait*2400,TimeUnit.MILLISECONDS);	//try acquire for as long as not in a hurry
		}catch(InterruptedException e)
			{
			
			}
		}
		else	//we have no time to spend, we need to get it NOW!
		{
				isAcquired=equipments.get(name).tryAcquire(amount);	//try acquire for once with top preference than other threads
		}
		
		return isAcquired;
	}
	*/
}
